package hos.thread

import android.util.Log
import hos.thread.executor.TS
import hos.thread.hander.MH

/**
 * <p>Title: RunnableLife </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2023/8/4 21:00
 * @version : 1.0
 */
abstract class RunnableLife : RunnableThis {

    private var isCancel = false

    fun isCancel(): Boolean {
        return isCancel
    }

    fun reset(): RunnableLife {
        isCancel = false
        return this
    }

    fun cancel() {
        changedStatus(ThreadOption.Status.ON_CANCEL)
        isCancel = true
    }

    protected var onThrowable: (Throwable.(String) -> Unit)? = null

    protected var onCancel: (String.() -> Unit)? = null

    protected var onProgress: (Double.() -> Unit)? = null

    protected var onStart: (RunnableLife.(String) -> Unit)? = null

    private var listener: (RunnableLife.(ThreadOption.Status) -> Unit)? = null

    private var status = ThreadOption.Status.ON_NONE

    protected fun changedStatus(status: ThreadOption.Status) {
        this.status = status
        listener?.invoke(this, status)
    }

    fun isStatus(status: ThreadOption.Status): Boolean {
        return this.status == status
    }

    open fun isRunning(): Boolean {
        return isStatus(ThreadOption.Status.ON_START) || isStatus(ThreadOption.Status.ON_RUNNING)
    }

    open fun setStatusListener(listener: RunnableLife.(ThreadOption.Status) -> Unit): RunnableLife {
        this.listener = listener
        return this
    }

    open fun onStart(start: RunnableLife.(String) -> Unit): RunnableLife {
        this.onStart = start
        return this
    }

    open fun onProgress(progress: Double.() -> Unit): RunnableLife {
        this.onProgress = progress
        return this
    }

    open fun onCatch(throwable: Throwable.(String) -> Unit): RunnableLife {
        this.onThrowable = throwable
        return this
    }

    open fun onCancel(onCancel: String.() -> Unit): RunnableLife {
        this.onCancel = onCancel
        return this
    }

    protected open fun postStart(msg: String = "开始") {
        runUI {
            Log.d("Thread", "run: onStart")
            onStart?.invoke(this, msg)
        }
        changedStatus(ThreadOption.Status.ON_START)
    }

    protected open fun postCancel(msg: String = "取消") {
        runUI {
            Log.d("Thread", "run: onCancel")
            onCancel?.invoke(msg)
        }
    }

    protected open fun postProgress(value: Double) {
        runUI {
            onProgress?.invoke(value)
        }
    }

    protected open fun postThrowable(
        value: Throwable,
        threadName: String = Thread.currentThread().name,
    ) {
        runUI {
            Log.e("Thread", "run: onError", value)
            onThrowable?.invoke(value, threadName)
        }
        changedStatus(ThreadOption.Status.ON_THROWABLE)
    }

    protected open fun runUI(run: () -> Unit) {
        MH.run {
            run.invoke()
        }
    }

    abstract fun progressUpdate(value: Double)

    open fun onDestroy() {
        cancel()
        changedStatus(ThreadOption.Status.ON_DESTROY)
        TS.remove(this)
        onProgress = null
        onCancel = null
        onStart = null
        onThrowable = null
        listener = null
    }
}